package com.yzf.wisecoder.wisecoderservice.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yzf.uidgeneratorcore.impl.CachedUidGenerator;
import com.yzf.wisecoder.wisecodercommon.constant.Constant;
import com.yzf.wisecoder.wisecodercommon.exception.RRException;
import com.yzf.wisecoder.wisecodercommon.utils.BeanCopyUtils;
import com.yzf.wisecoder.wisecodercommon.utils.SecurityUtils;
import com.yzf.wisecoder.wisecoderservice.service.*;
import com.yzf.wisecoder.wisecoderstorage.mysql.dao.ViewConfigDao;
import com.yzf.wisecoder.wisecoderstorage.mysql.entity.*;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * @author jianghuiyong
 * @email jianghuiyong@yunzhangfang.com
 * @date 2020-05-12 10:20:48
 */
@Service("viewConfigService")
@AllArgsConstructor
public class ViewConfigServiceImpl extends ServiceImpl<ViewConfigDao, ViewConfigEntity> implements ViewConfigService {

    private final CachedUidGenerator cachedUidGenerator;
    private final ViewDatasourceService viewDatasourceService;
    private final ViewConfigPublishService viewConfigPublishService;
    private final ViewDatasourcePublishService viewDatasourcePublishService;
    private final ViewDbService viewDbService;
    private final ViewDbPublishService viewDbPublishService;

    @Override
    public List<ViewConfigEntity> queryList(Long projectId) {
        List<ViewConfigEntity> list = list(new QueryWrapper<ViewConfigEntity>()
                .eq("project_id", projectId));
        return list;
    }

    @Override
    public boolean removeByProjectId(List<Long> projectIds) {
        return remove(new QueryWrapper<ViewConfigEntity>().in("project_id", projectIds));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdateViewConfig(ViewConfigEntity viewConfigEntity) {
        ViewConfigEntity viewConfigEntity1 = getOne(new QueryWrapper<ViewConfigEntity>()
                .eq("view_name", viewConfigEntity.getViewName()));
        if (viewConfigEntity1 != null && (viewConfigEntity.getViewId() == null
                || viewConfigEntity.getViewId().longValue() != viewConfigEntity1.getViewId().longValue())) {
            throw new RRException("大屏名称不能重复");
        }
        if (viewConfigEntity.getViewId() == null) {
            viewConfigEntity.setCreator(SecurityUtils.getUserId())
                    .setViewId(cachedUidGenerator.getUID())
                    .setCreateTime(LocalDateTime.now());
        }

        // 修改模块的数据源配置
        JSONObject viewTemConfigJsonObject = JSONObject.parseObject(viewConfigEntity.getViewTemConfig());

        Map<String, JSONObject> profiles = viewTemConfigJsonObject.getJSONObject("profiles")
                .toJavaObject(new TypeReference<Map<String, JSONObject>>() {
                });
        List<ViewDatasourceEntity> viewDatasourceEntityList = Lists.newArrayList();
        Iterator<Map.Entry<String, JSONObject>> it = profiles.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, JSONObject> entry = it.next();
            String moduleId = entry.getKey();
            JSONObject value = entry.getValue();
            JSONObject dataSourceJsonObject = value.getJSONObject("datasource");
            ViewDatasourceEntity viewDatasourceEntity = dataSourceJsonObject.toJavaObject(ViewDatasourceEntity.class);
            if (Constant.DATASOURCETYPE.STATIC.getType().equals(viewDatasourceEntity.getSourceType())) {
                continue;
            }
            viewDatasourceEntity.setModuleId(moduleId)
                    .setProjectId(viewConfigEntity.getProjectId())
                    .setViewId(viewConfigEntity.getViewId())
                    .setCreator(SecurityUtils.getUserId())
                    .setCreateTime(LocalDateTime.now())
                    .setSourceId(cachedUidGenerator.getUID());
            viewDatasourceEntityList.add(viewDatasourceEntity);
            //更新内容为ID
            dataSourceJsonObject.remove("executeText");
            dataSourceJsonObject.put("sourceId", viewDatasourceEntity.getSourceId().toString());
            value.put("datasource", dataSourceJsonObject);
            entry.setValue(value);
        }
        // 保存大屏展示配置
        viewTemConfigJsonObject.put("profiles", profiles);
        viewConfigEntity.setViewTemConfig(viewTemConfigJsonObject.toJSONString()).setPublished(Boolean.FALSE);
        saveOrUpdate(viewConfigEntity);
        // 保存数据源配置
        viewDatasourceService.saveOrUpdateViewDataSourceList(viewConfigEntity.getViewId(), viewDatasourceEntityList);
        return true;
    }

    @Override
    public boolean removeViewConfig(Long viewId) {
        removeById(viewId);
        viewDatasourceService.removeByViewId(viewId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pushViewConfig(Long viewId) {
        //登录用户ID
        Long userId = SecurityUtils.getUserId();
        LocalDateTime now = LocalDateTime.now();
        List<Long> dbIds = Lists.newArrayList();
        // 发布模板
        ViewConfigEntity viewConfigEntity = getById(viewId);
        ViewConfigPublishEntity viewConfigPublishEntity = new ViewConfigPublishEntity();
        BeanUtils.copyProperties(viewConfigEntity, viewConfigPublishEntity);
        viewConfigPublishEntity.setCreator(userId)
                .setCreateTime(now);
        viewConfigPublishService.saveOrUpdate(viewConfigPublishEntity);
        // 修改发布状态
        viewConfigEntity.setPublished(Boolean.TRUE);
        updateById(viewConfigEntity);
        // 发布组件数据源配置
        List<ViewDatasourceEntity> viewDatasourceEntityList = viewDatasourceService.queryByViewId(viewId);
        if (CollectionUtil.isNotEmpty(viewDatasourceEntityList)) {
            List<ViewDatasourcePublishEntity> viewDatasourcePublishEntityList = BeanCopyUtils.copyList(viewDatasourceEntityList, ViewDatasourcePublishEntity.class);
            viewDatasourcePublishEntityList.forEach(viewDatasourcePublishEntity -> {
                viewDatasourcePublishEntity.setCreator(userId).setCreateTime(now);
                dbIds.add(viewDatasourcePublishEntity.getDbId());
            });
            viewDatasourcePublishService.removeByViewId(viewId);
            viewDatasourcePublishService.saveOrUpdateBatch(viewDatasourcePublishEntityList);
        }
        // 发布项目数据库配置
        if (CollectionUtil.isNotEmpty(dbIds)) {
            List<ViewDbEntity> dbEntityList = viewDbService.queryByDbIds(dbIds);
            List<ViewDbPublishEntity> viewDbPublishEntityList = BeanCopyUtils.copyList(dbEntityList, ViewDbPublishEntity.class);
            viewDbPublishEntityList.forEach(viewDbPublishEntity -> viewDbPublishEntity.setCreator(userId).setCreateTime(now));
            viewDbPublishService.saveOrUpdateBatch(viewDbPublishEntityList);
        }
        return true;
    }

    @Override
    public boolean removePublish(Long viewId) {
        viewConfigPublishService.removeById(viewId);
        viewDatasourcePublishService.remove(new QueryWrapper<ViewDatasourcePublishEntity>().eq("view_id", viewId));
        List<Long> dbIds = Lists.newArrayList();
        List<ViewDatasourceEntity> viewDatasourceEntityList = viewDatasourceService.queryByViewId(viewId);
        if (CollectionUtil.isNotEmpty(viewDatasourceEntityList)) {
            viewDatasourceEntityList.forEach(viewDatasourceEntity -> dbIds.add(viewDatasourceEntity.getDbId()));
        }
        viewDbPublishService.removeByIds(dbIds);
        return false;
    }

    @Override
    public ViewConfigEntity queryViewConfig(Long viewId) {
        ViewConfigEntity viewConfigEntity = getById(viewId);
        // 修改模块的数据源配置
        JSONObject viewTemConfigJsonObject = JSONObject.parseObject(viewConfigEntity.getViewTemConfig());

        Map<String, JSONObject> profiles = viewTemConfigJsonObject.getJSONObject("profiles")
                .toJavaObject(new TypeReference<Map<String, JSONObject>>() {
                });
        Iterator<Map.Entry<String, JSONObject>> it = profiles.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, JSONObject> entry = it.next();
            JSONObject value = entry.getValue();
            JSONObject dataSourceJsonObject = value.getJSONObject("datasource");
            ViewDatasourceEntity viewDatasourceEntity = dataSourceJsonObject.toJavaObject(ViewDatasourceEntity.class);
            if (Constant.DATASOURCETYPE.STATIC.getType().equals(viewDatasourceEntity.getSourceType())) {
                continue;
            }
            ViewDatasourceEntity viewDatasourceEntity1 = viewDatasourceService.getById(viewDatasourceEntity.getSourceId());
            //更新内容为ID
            dataSourceJsonObject.remove("sourceId");

            dataSourceJsonObject.put("executeText", viewDatasourceEntity1.getExecuteText());
            value.put("datasource", dataSourceJsonObject);
            entry.setValue(value);
        }
        // 保存大屏展示配置
        viewTemConfigJsonObject.put("profiles", profiles);
        viewConfigEntity.setViewTemConfig(viewTemConfigJsonObject.toJSONString());
        return viewConfigEntity;
    }
}